package com.dream.libxrec.utils;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.media.Image;
import android.util.Log;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

public class ImageUtils {
    public static final int COLOR_FormatI420 = 1;
    public static final int COLOR_FormatNV21 = 2;

    public static final int COLOR_FormatNV12 = 3;
    public static final String TAG = "ImageUtils";
    public static boolean isDEBUG = false;

    public static boolean isImageFormatSupported(Image image) {
        int format = image.getFormat();
        switch (format) {
            case ImageFormat.YUV_420_888:
            case ImageFormat.NV21:
            case ImageFormat.YV12:
                return true;
        }
        return false;
    }

    public static byte[] getDataFromImage(Image image,
                                        int colorFormat) {

        Rect crop = image.getCropRect();
        int width = image.getWidth();
        int height = image.getHeight();
        byte[] mYuvBuffer = new byte[width*height*3/2];
        int format = image.getFormat();
        Log.d(TAG, "crop width: " + crop.width() + ", height: " + crop.height());
        Image.Plane[] planes = image.getPlanes();

        byte[] rowData = new byte[planes[0].getRowStride()];

        int channelOffset = 0;
        int outputStride = 1;
        for (int i = 0; i < planes.length; i++) {
            switch (i) {
                case 0:
                    channelOffset = 0;
                    outputStride = 1;
                    break;
                case 1:
                    if (colorFormat == COLOR_FormatI420) {
                        channelOffset = width * height;
                        outputStride = 1;
                    } else if (colorFormat == COLOR_FormatNV21) {
                        channelOffset = width * height + 1;
                        outputStride = 2;
                    } else if (colorFormat == COLOR_FormatNV12) {
                        channelOffset = width * height;
                        outputStride = 2;
                    }
                    break;
                case 2:
                    if (colorFormat == COLOR_FormatI420) {
                        channelOffset = (int) (width * height * 1.25);
                        outputStride = 1;
                    } else if (colorFormat == COLOR_FormatNV21) {
                        channelOffset = width * height;
                        outputStride = 2;
                    } else if (colorFormat == COLOR_FormatNV12) {
                        channelOffset = width * height + 1;
                        outputStride = 2;
                    }
                    break;
                default:
            }
            ByteBuffer buffer = planes[i].getBuffer();
            int rowStride = planes[i].getRowStride();
            int pixelStride = planes[i].getPixelStride();

            int shift = (i == 0) ? 0 : 1;
            int w = width >> shift;
            int h = height >> shift;
            buffer.position(rowStride * (crop.top >> shift) + pixelStride * (crop.left >> shift));
            for (int row = 0; row < h; row++) {
                int length;
                if (pixelStride == 1 && outputStride == 1) {
                    length = w;
                    buffer.get(mYuvBuffer, channelOffset, length);
                    channelOffset += length;
                } else {
                    length = (w - 1) * pixelStride + 1;
                    buffer.get(rowData, 0, length);
                    for (int col = 0; col < w; col++) {
                        mYuvBuffer[channelOffset] = rowData[col * pixelStride];
                        channelOffset += outputStride;
                    }
                }
                if (row < h - 1) {
                    buffer.position(buffer.position() + rowStride - length);
                }
            }
        }
        return mYuvBuffer;
    }

    /**
     * 将YUV420_888的image转为jpg并保存
     * @param fileName
     * @param image
     * @return
     */
    public static boolean compressToJpeg(String fileName, Image image) {

        byte[] nv21 = getDataFromImage(image, COLOR_FormatNV21);
        return compressToJpeg(fileName,nv21,image.getWidth(),
                image.getHeight());
    }

    public static boolean compressToJpeg(String fileName,
                                         byte[] nv21,int width,
                                         int height) {
        FileOutputStream outStream;
        try {
            outStream = new FileOutputStream(fileName);
        } catch (IOException ioe) {
            throw new RuntimeException("Unable to create output file " + fileName, ioe);
        }
        YuvImage yuvImage = new YuvImage(nv21, ImageFormat.NV21,
                width,height, null);
        Rect rect = new Rect(0,0,width,height);
        return yuvImage.compressToJpeg(rect, 100, outStream);
    }

    /**
     * NV21转Bitmap
     * @param nv21
     * @param width
     * @param height
     * @param quality 质量 1~100，取值范围 0-100，100为品质最高
     * @return
     */
    public static Bitmap nv21toBitmap(byte[] nv21,int width,
                                     int height,int quality){
        YuvImage yuvimage=new YuvImage(nv21,  ImageFormat.NV21,width,height, null);
        ByteArrayOutputStream baos = new  ByteArrayOutputStream();
        yuvimage.compressToJpeg(new Rect(0, 0,width, height), quality,
                baos);
        byte[] data = baos.toByteArray();

        return BitmapFactory.decodeByteArray(data, 0,data.length);
    }
}
